/**
 * 刷新 token 机制
 */

// 刷新token的锁(标识); true: 正在刷新;  false: 没有刷新; undefined: 未登录
let __refreshTokenLock__ = false

// 放行白名单; 里面存储的是不需要验证 token 的API
const permitThroughWhiteList = []
// accessToken 有效时间(单位: 秒);
const accessTokenValidTime = 600
// refreshToken 有效时间(单位: 秒);
const refreshTokenValidTime = 720

/**
 * 检查token
 * @returns true: 直接放行;  false: 不能放行
 */
function checkToken(axios) {
  return new Promise((resolve, reject) => {
    // 接口访问的token标识;  todo 根据项目来获取(一般都是从storage里获取)
    const accessToken = ''
    // 用来刷新 accessToken 的标识; todo 根据项目来获取(一般都是从storage里获取)
    const refreshToken = ''
    // 到期状态
    const expireStatus = checkAllowRefresh()

    if (expireStatus === 'needless') {// 不需要刷新token
      resolve(true)
    } else if (expireStatus === 'needRefresh') {// 需要刷新token
      return refreshToken()
    } else if (expireStatus === 'notLogin') {// 未登录
      refreshFail()
      reject(false)
    }
  })
}

/**
 * 刷新token
 */
function refreshToken() {
  return new Promise((resolve, reject) => {
    if (__refreshTokenLock__ === false) { // 没刷新在刷新的情况
      __refreshTokenLock__ = true
      refreshApi().then(res => {
        // todo 将获取新的 accessToken / refreshToken / 获取token时间 进行保存到缓存中
        __refreshTokenLock__ = false

        resolve(true)
      }).catch(err => {
        __refreshTokenLock__ = undefined
        
        refreshFail()

        reject(false)
      })
    } else if (__refreshTokenLock__ === true) { // 正在刷新情况
      const checkLock = () => {
        setTimeout(() => {
          if (__refreshTokenLock__ === undefined) {
            refreshFail()
          }
        }, 500)

        __refreshTokenLock__ === false ? resolve(true) : checkLock()
      }
      checkLock()
    } else {
      refreshFail()
      reject(false)
    }
  })
}

/**
 * 是否允许刷新token
 * @returns 
 */
function checkAllowRefresh() {	
	// 当前使用时间
	const nowTime = new Date().getTime()
	
	// 获取token时的时间; 此token time 是在登录成功后存储在storage里的时间戳(单位: 毫秒); todo 根据真实情况获取
	const takeTokenTime = ''
		
  // 将设置的到期时间转换成毫秒
	const accessTokenTimeout = Number(accessTokenValidTime * 1000)
	const refreshTokenTimeout = Number(refreshTokenValidTime * 1000)

	// accessToken 到期时间
	let  accessTokenEnd = Number(takeTokenTime + accessTokenTimeout)
	// refreshToken 到期时间
	let  refreshTokenEnd = Number(takeTokenTime + refreshTokenTimeout)

	
	
  /**
   * accessToken: 到期时间 <= 当前时间  则说明此token到期
   * refreshToken: 到期时间 <= 当前时间t  则说明此token到期
   * 
   * 如果 accessToken && refreshToken 都到期了, 则不能刷新token
   */
  const accessTokenIsExpire = accessTokenEnd <= nowTime
  const refreshTokenIsExpire = refreshTokenEnd <= nowTime

  // accessToken没有到期, 则不需要刷新token
  if (!accessTokenIsExpire) {
    return 'needless'
  } else if (!refreshTokenIsExpire && accessTokenIsExpire) { // refreshToken没到期并且accessToken到期, 则需要刷新token
    return 'needRefresh'
  } else { // 其余情况就是 两个token都到期了,所以就是未登录
    return 'notLogin'
  }
}

// todo 模拟刷新token的API接口方法, 具体项目用可删除替换
function refreshApi() {
  return new Promise((resolve, reject) => {
    resolve(true)
  })
}

/**
 * 刷新失败的处理方法;
 * 比如: 刷新失败后清除缓存信息,并且跳转到登录页等
 * // todo 刷新视频的情况可以将所有的请求和storage(Vuex)等信息清除掉, 再跳转到登录页(根据业务来决定跳转)
 */
function refreshFail() {}

// todo 如使用模块化时可使用 export 输出
// export {
//   checkToken
// }